package com.woniuxy.microloanserver.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.woniuxy.bean.BillBean;
import com.woniuxy.bean.MemberEntity;
import com.woniuxy.bean.ResultBean;
import com.woniuxy.microloanserver.bean.*;
import com.woniuxy.microloanserver.constant.LoanOrderConst;
import com.woniuxy.microloanserver.feign.SysFeign;
import com.woniuxy.microloanserver.service.LoanOrderService;
import com.woniuxy.microloanserver.service.UserQuotaService;
import com.woniuxy.microloanserver.util.MoneyUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Description: 用户申请贷款控制层接口
 *
 * @Auther: HanLei
 * @Date: 2021/4/19:14:36
 */
@RefreshScope
@Slf4j
@Api(tags = "用户申请贷款接口")
@RestController
@RequestMapping(value = "/loan/loan", produces = {"application/json;charset=utf-8"})
public class UserLoanController {

    @Resource
    private UserQuotaService userQuotaServiceImpl;
    @Resource
    private LoanOrderService loanOrderServiceImpl;
    @Resource
    private SysFeign sysFeign;

    /*
     * Description :   用户申请借款业务
     * ChangeLog : 1. 创建 (2021/4/19 14:41 );
     * @param null
     * @return null
     */
    @ApiOperation("用户申请借款接口")
    @PostMapping("/applyLoan")
    public ResultBean applyForLoan (@ApiParam(value = "贷款订单对象", required = true) @RequestBody LoanOrderBean loanOrderBean) {

        log.info("LoanOrderBean---:{}", loanOrderBean);
        try {
            //参数校验
            boolean flag = judgeParameter(loanOrderBean);
            if (flag) {
                return ResultBean.builder().code(400).msg("参数异常，请稍后重试！").build();
            }
            //获取用户额度信息
            UserLoanQuotaInfo userLoanQuota = userQuotaServiceImpl.getUserLoanQuota(loanOrderBean.getFkUserId());
            if (userLoanQuota == null) {
                return ResultBean.builder().code(400).msg("用户不存在！").build();
            }
            //订单数据验证（额度状态验证、可用额度验证、期数利率验证）
            if (judegOrderData(loanOrderBean, userLoanQuota)) {
                return ResultBean.builder().code(400).msg("数据异常，请稍后重试！").build();
            }
            //生成订单数据(在方法参数对象中加入订单编号和创建时间)
            Date now = new Date();
            String orderNumber = "" + loanOrderBean.getFkUserId() + now.getTime();//订单编号=用户id+当前系统时间戳
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String createTime = dateFormat.format(now); //订单创建时间
            loanOrderBean.setOrderNumber(orderNumber);
            loanOrderBean.setCreateTime(createTime);
            //获取订单分期对象与还款账单对象
            Map<String, Object> stageAndBill = createBean(loanOrderBean, userLoanQuota);
            LoanOrderStageBean stageBean = null;
            List<LoanRepaymentBillBean> bills = null;
            if (stageAndBill != null) {
                stageBean = (LoanOrderStageBean) stageAndBill.get(LoanOrderConst.stageAndBill.STAGE);
                bills = (List<LoanRepaymentBillBean>) stageAndBill.get(LoanOrderConst.stageAndBill.BILL);
            } else {
                return ResultBean.builder().code(500).msg("对象生成异常，请稍后重试！").build();
            }
            if (loanOrderBean != null && ! StringUtils.isEmpty(loanOrderBean.getProvider())) {
                loanOrderBean.setProvider("翔瑞小贷公司");
            }

            //调用表现层接口将订单对象、订单分期对象、还款账单对象存入数据库
            loanOrderServiceImpl.applyLoan(loanOrderBean, stageBean, bills);
            //更新已用额度
            BigDecimal newUsedQuota = userLoanQuota.getUsedQuota().add(loanOrderBean.getSumMoney(),
                    new MathContext(2, RoundingMode.DOWN));
            userLoanQuota.setUsedQuota(newUsedQuota);
            userQuotaServiceImpl.update(userLoanQuota);
            //添加余额
            BillBean billBean = new BillBean();
            billBean.setProductName(LoanOrderConst.PRODUCT_NAME); //产品名称（祥瑞贷）
            billBean.setProductType(LoanOrderConst.ProductType.LOAN); //产品类型（借款）
            String money = "-" + loanOrderBean.getSumMoney().toString();
            billBean.setModifiedPrice(Double.valueOf(money)); //金额
            billBean.setMemberName(loanOrderBean.getUserName()); //用户名
            //设置为借贷产品,避免支付密码验证
            billBean.setIsloan(1);
           // billBean.setPayPassword("445566");
            billBean.setPayType("余额");
            String res = sysFeign.addWalletBalance(billBean);

            int resCode = JSON.parseObject(
                    JSON.parseObject(res).getString("code"), Integer.class);//用户资料
            log.info("code{}", resCode);
            if (resCode == 200) {
                return ResultBean.builder().code(200).msg("借款成功！").build();
            } else {
                return ResultBean.builder().code(500).msg("系统繁忙，请稍后重试！").build();
            }
        } catch (Exception e) {
            log.error("我也不知道是什么异常：{}", e);
            return ResultBean.builder().code(500).msg("系统繁忙，请稍后重试！").build();
        }
    }

    /*
     * Description :   订单对象参数校验方法
     * ChangeLog : 1. 创建 (2021/4/19 21:56 );
     * @param loanOrderBean  订单对象
     * @return flag   true:不合法 false:合法
     */
    private boolean judgeParameter (LoanOrderBean loanOrderBean) {
        boolean flag = false;
        if (loanOrderBean == null) {
            flag = true;
        }
        //用户id验证
        else if (loanOrderBean.getFkUserId() == null) {
            flag = true;
        }
        //金额数据格式验证，必须为100的正整数倍
        else if (loanOrderBean.getSumMoney() == null || Integer.valueOf(loanOrderBean.getSumMoney().toString()) % 100 != 0) {

            flag = true;
        }
        //利率数据非空验证
        else if (loanOrderBean.getInterestRate() == null) {
            flag = true;
        }
        //还款方式验证
        else if (loanOrderBean.getRepaymentMethod().intValue() != LoanOrderConst.RepaymentMethod.RECYCL &&
                loanOrderBean.getRepaymentMethod().intValue() != LoanOrderConst.RepaymentMethod.STAGE) {
            flag = true;
        }
        //还款期数验证(1、3、6、9、12)
        else if (loanOrderBean.getStageNum().intValue() != LoanOrderConst.StageNum.ONE &&
                loanOrderBean.getStageNum().intValue() != LoanOrderConst.StageNum.THREE &&
                loanOrderBean.getStageNum().intValue() != LoanOrderConst.StageNum.SIX &&
                loanOrderBean.getStageNum().intValue() != LoanOrderConst.StageNum.NINE &&
                loanOrderBean.getStageNum().intValue() != LoanOrderConst.StageNum.TWELVE) {
            flag = true;
        }
        return flag;
    }

    /*
     * Description :   期数与利率验证
     * ChangeLog : 1. 创建 (2021/4/20 9:40 );
     * @param userLoanInterestRate 用户贷款利率对象
     * @param stages    期数
     * @return rate 匹配到的利率
     */
    private BigDecimal judegRate (UserLoanInterestRateBean userLoanInterestRate, Integer stages) {
        BigDecimal rate = null;
        switch (stages) {
            case LoanOrderConst.StageNum.ONE:
                rate = userLoanInterestRate.getDaily();
                break;
            case LoanOrderConst.StageNum.THREE:
                rate = userLoanInterestRate.getThree();
                break;
            case LoanOrderConst.StageNum.SIX:
                rate = userLoanInterestRate.getSix();
                break;
            case LoanOrderConst.StageNum.NINE:
                rate = userLoanInterestRate.getNine();
                break;
            case LoanOrderConst.StageNum.TWELVE:
                rate = userLoanInterestRate.getTwelve();
                break;
        }
        return rate;
    }

    /*
     * Description :   验证订单数据
     *                  额度状态验证、可用额度验证、期数利率验证
     * ChangeLog : 1. 创建 (2021/4/20 10:06 );
     * @param loanOrderBean 订单对象
     * @param userLoanQuota 用户贷款额度信息对象
     * @return flag 数据标志位   false：无异常   true：异常
     */
    private boolean judegOrderData (LoanOrderBean loanOrderBean, UserLoanQuotaInfo userLoanQuotaInfo) {
        boolean flag = false;
        //额度状态验证
        Integer quotaStatus = userLoanQuotaInfo.getQuotaStatus();//额度状态
        if (quotaStatus == LoanOrderConst.QuotaStatus.FROZEN) {
            //额度被冻结
            flag = true;
        }
        //额度数据验证（借款金额与可用金额）
        BigDecimal useableQuota = userLoanQuotaInfo.getTotalQuota().subtract(userLoanQuotaInfo.getUsedQuota());//总额度-已用额度=可用额度
        BigDecimal loanMoney = loanOrderBean.getSumMoney();//借款金额
        int quotaJudgeRes = useableQuota.compareTo(loanMoney);//额度判断结果
        if (quotaJudgeRes < 0) {
            //可用金额小于借款金额
            flag = true;
        }
        //利率数据合法性验证（参数中的利率与实际利率）
//        Integer stageNum = loanOrderBean.getStageNum();//期数
//        UserLoanInterestRateBean userLoanInterestRate = userLoanQuotaInfo.getUserLoanInterestRate();//用户贷款利率对象
//        BigDecimal userRate = judegRate(userLoanInterestRate, stageNum);
//        //判断传入的利率是否与用户实际利率相等
//        if (userRate == null || userRate.compareTo(loanOrderBean.getInterestRate()) != 0) {
//            flag = true;
//        }
        return flag;
    }

    /*
     * Description :   根据订单对象与用户贷款额度信息对象，生成订单分期对象与还款账单对象
     * ChangeLog : 1. 创建 (2021/4/20 10:42 );
     * @param loanOrderBean 订单对象
     * @param userLoanQuota 用户贷款额度信息对象
     * @return stageAndBill 订单分期对象与还款账单对象
     */
    private Map<String, Object> createBean (LoanOrderBean loanOrderBean, UserLoanQuotaInfo userLoanQuota) {
        Map<String, Object> stageAndBill = null; //封装订单分期对象与还款账单对象
        try {
            Integer stageNum = loanOrderBean.getStageNum();//期数
            BigDecimal loanMoney = loanOrderBean.getSumMoney();//借款金额
            //根据订单还款期数生成订单分期数据
            LoanOrderStageBean loanOrderStageBean = new LoanOrderStageBean();//订单分期对象
            loanOrderStageBean.setFkLoanOrderNumber(loanOrderBean.getOrderNumber()); //订单编号
            loanOrderStageBean.setFkUserId(loanOrderBean.getFkUserId()); //用户id
            loanOrderStageBean.setTotPmts(stageNum); //总期数
            //每期本金 = 贷款金额 / 期数
            BigDecimal principal = loanMoney.divide(new BigDecimal(stageNum.toString()), 2, RoundingMode.DOWN);
            loanOrderStageBean.setPrincipal(principal);
            //每期利息 = 每期本金 * 利率
            BigDecimal interest = principal.multiply(principal, new MathContext(2, RoundingMode.DOWN));
            loanOrderStageBean.setInterest(interest);
            //每期分期服务费 = 总服务费 / 期数
            BigDecimal serviceCharge = null;
            if (loanOrderBean.getRepaymentMethod().intValue() == LoanOrderConst.RepaymentMethod.RECYCL) {
                //随借随还，分期服务费为0
                serviceCharge = new BigDecimal("0.00");
            } else {
                //分期还款
                serviceCharge = loanOrderBean.getServiceCharge().divide(new BigDecimal(stageNum.toString()), 2, RoundingMode.DOWN);
            }
            loanOrderStageBean.setServiceCharge(serviceCharge);
            //生成账单数据
            List<LoanRepaymentBillBean> bills = new ArrayList<>();
            for (int i = 1; i < stageNum + 1; i++) {
                LoanRepaymentBillBean bill = new LoanRepaymentBillBean();
                bill.setFkLoanOrderNumber(loanOrderBean.getOrderNumber()); //订单编号
                bill.setFkUserId(loanOrderBean.getFkUserId()); //用户id
                bill.setPrincipal(principal); //本金
                bill.setInterest(interest); //利息
                bill.setServiceCharge(serviceCharge); //每期服务费
                bill.setPeriod(i); //账单期数
                Calendar calendar = Calendar.getInstance(); //日历类对象
                calendar.set(Calendar.DAY_OF_MONTH, userLoanQuota.getRepaymentTime()); //设置还款日
                calendar.add(Calendar.MONTH, i); //从下个月还款日开始
                Date date = calendar.getTime();
                DateFormat dataFormat = new SimpleDateFormat("yyyy-MM-dd");
                bill.setRepaymentDate(dataFormat.format(date));
                bills.add(bill);
            }
            stageAndBill = new HashMap<>();
            stageAndBill.put(LoanOrderConst.stageAndBill.STAGE, loanOrderStageBean);
            stageAndBill.put(LoanOrderConst.stageAndBill.BILL, bills);
        } catch (Exception e) {
            log.error("对象生成异常：{}", e);
        } finally {
            return stageAndBill;
        }
    }

}
